Attribute VB_Name = "Analysis"
Option Explicit

'Returns the unique ID of the bot these two bots share as a common ancestor
'Returns 0 if no common ancestor found
Public Function FindClosestCommonAncestor(bot1 As Integer, bot2 As Integer, ByRef simNum As Long) As Long
Dim i As Integer
Dim x As Integer
Dim counter1 As Integer
Dim counter2 As Integer

  FindClosestCommonAncestor = 0
  If rob(bot1).FName <> rob(bot2).FName Then Exit Function
  
  i = rob(bot1).AncestorIndex
  x = rob(bot2).AncestorIndex
  counter1 = 0
  counter2 = 0
  
  'Check the special cases where one bot is a direct descendent of the other
  'Return the ancestor's ID if one is the ancestor of the other
  While counter1 < 500
     If rob(bot1).Ancestors(i).num = rob(bot2).AbsNum And _
        rob(bot1).Ancestors(i).sim = rob(bot2).sim Then
        FindClosestCommonAncestor = rob(bot1).Ancestors(i).num
        simNum = rob(bot1).Ancestors(i).sim
        Exit Function
      End If
      counter1 = counter1 + 1
      i = i - 1
      If i < 0 Then i = 500
  Wend
  counter1 = 0
  i = rob(bot2).AncestorIndex
  While counter1 < 500
     If rob(bot2).Ancestors(i).num = rob(bot1).AbsNum And _
        rob(bot2).Ancestors(i).sim = rob(bot1).sim Then
        FindClosestCommonAncestor = rob(bot2).Ancestors(i).num
        simNum = rob(bot2).Ancestors(i).sim
        Exit Function
      End If
      counter1 = counter1 + 1
      i = i - 1
      If i < 0 Then i = 500
  Wend
    
  counter1 = 0
  i = rob(bot1).AncestorIndex

  While counter1 < 500
    counter2 = 0
    While counter2 < 500
      If rob(bot1).Ancestors(i).num = rob(bot2).Ancestors(x).num And _
         rob(bot1).Ancestors(i).sim = rob(bot2).Ancestors(x).sim Then
        FindClosestCommonAncestor = rob(bot1).Ancestors(i).num
        simNum = rob(bot1).Ancestors(i).sim
        Exit Function
      End If
      counter2 = counter2 + 1
      x = x - 1
      If x < 0 Then x = 500
    Wend
    i = i - 1
    If i < 0 Then i = 500
    counter1 = counter1 + 1
  Wend
End Function

'Returns the genetic distance from this bot to an ancestor
'Returns -1 if if no ancestor found
Public Function GeneticDistanceToAncestor(n As Integer, ancestorNum As Long, sim As Long) As Long
Dim i As Integer
Dim counter As Integer

  GeneticDistanceToAncestor = 0
  
  'Return 0 if the bot is the ancestor.
  If rob(n).AbsNum = ancestorNum Then Exit Function
  
  i = rob(n).AncestorIndex
  
  'Start with the mutations this bot has experienced itself
  GeneticDistanceToAncestor = rob(n).LastMut
  
  counter = 0
  While counter < 500
    'Add the mutations each ancestor had at the time
    GeneticDistanceToAncestor = GeneticDistanceToAncestor + rob(n).Ancestors(i).mut
    If rob(n).Ancestors(i).num = ancestorNum And _
       rob(n).Ancestors(i).sim = sim Then Exit Function
    i = i - 1
    If i < 0 Then i = 500
    counter = counter + 1
  Wend
  
  'No ancestor found
  GeneticDistanceToAncestor = -1
  
End Function

'Returns the generational distance from this bot to an ancestor
'Returns -1 if if no ancestor found
Public Function GenerationalDistanceToAncestor(n As Integer, ancestorNum As Long, sim As Long) As Long
Dim i As Integer
Dim counter As Integer
 
  GenerationalDistanceToAncestor = 0

  'Return 0 if the bot is the ancestor.
  If rob(n).AbsNum = ancestorNum Then Exit Function

  i = rob(n).AncestorIndex
  
  'Start with 1.  If one bot is the parent of the other, then distance is 1
  GenerationalDistanceToAncestor = 1
  
  counter = 0
  While counter < 500
    'Count the number of ancestors
    If rob(n).Ancestors(i).num = ancestorNum And _
       rob(n).Ancestors(i).sim = sim Then Exit Function
    GenerationalDistanceToAncestor = GenerationalDistanceToAncestor + 1
    i = i - 1
    If i < 0 Then i = 500
    counter = counter + 1
  Wend

  ' No ancestor found
  GenerationalDistanceToAncestor = -1
  
End Function


'Returns the genetic distance between two extant bots if they share a common ancestor
'Returns - 1 if there is no common ancestor.
Public Function FindGeneticDistance(bot1 As Integer, bot2 As Integer, closestAncestor As Long, sim As Long) As Long
'Dim closestAncestor As Long
'Dim sim As Long

 ' closestAncestor = FindClosestCommonAncestor(bot1, bot2, sim)
  If closestAncestor = 0 Then
    FindGeneticDistance = -1
    Exit Function
  Else
    FindGeneticDistance = GeneticDistanceToAncestor(bot1, closestAncestor, sim) + GeneticDistanceToAncestor(bot2, closestAncestor, sim)
  End If
End Function

'Returns the generational distance between two extant bots if they share a common ancestor
'Returns - 1 if there is no common ancestor.
Public Function FindGenerationalDistance(bot1 As Integer, bot2 As Integer, closestAncestor As Long, sim As Long) As Long
'Dim closestAncestor As Long
'Dim sim As Long

 ' closestAncestor = FindClosestCommonAncestor(bot1, bot2, sim)
  If closestAncestor = 0 Then
    FindGenerationalDistance = -1
    Exit Function
  Else
    FindGenerationalDistance = GenerationalDistanceToAncestor(bot1, closestAncestor, sim) + GenerationalDistanceToAncestor(bot2, closestAncestor, sim)
  End If
End Function

